package com.zxd.interview.conrruentbook;

import javax.management.*;
import javax.management.modelmbean.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * 多个线程修改hashmap问题
 *
 */
public class HashMapTestThreadUnSafe {

    /**
     * 同时并发执行的线程数
     */
    public static final int THREAD_COUNT = 200;

    /**
     * 执行的总次数
     */
    public static final int TOTAL_COUNT = 5000;

    /**
     * 待测试集合
     * 将hashmap 转为 线程安全集合
     */
//    private static Map<Integer,Integer> map = Collections.synchronizedMap(new HashMap<>());
    /**
     * hashmap 线程不安全
     */
    private static Map<Integer,Integer> map = new HashMap<>();

    public static void main(String[] args) throws InterruptedException {
        ExecutorService threadPool = Executors.newCachedThreadPool();
        /*
        * 信号量（英語：semaphore）又稱為信号标，是一个同步对象，用于保持在0至指定最大值之间的一个计数值。
        * 当线程完成一次对该semaphore对象的等待（wait）时，该计数值减一；当线程完成一次对semaphore对象的释放（release）时，
        * 计数值加一。
        * */
        final Semaphore semaphore = new Semaphore(THREAD_COUNT);
        final CountDownLatch countDownLatch = new CountDownLatch(TOTAL_COUNT);
        for (int i = 0; i < TOTAL_COUNT; i++) {
            final int count = i;
            threadPool.execute(() -> {
                try {
                    //如果令牌池空了，新进来的线程要等待
                    semaphore.acquire();
                    map.put(count, count);
                    //执行完成一个就释放一个
                    semaphore.release();
                } catch (Exception e) {
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        threadPool.shutdown();
        System.out.println("map的最终大小为====>>> " + map.size());


    }/*
    如果使用:
    - Collections.synchronizedMap(new HashMap<>()) 使用线程安全容器可以保证50000
    - HashMap<>() 线程不安全类大概率为5000以下的值
    */

}
